package com.franklin.ideaplugin.maphelper.resolver.impl.collection;

import cn.hutool.core.collection.CollectionUtil;
import com.franklin.ideaplugin.api.beans.declaration.IDeclaration;
import com.franklin.ideaplugin.api.utils.psi.PsiClassUtils;
import com.franklin.ideaplugin.api.utils.psi.PsiExpressionUtils;
import com.franklin.ideaplugin.maphelper.beans.colmember.IColMember;
import com.franklin.ideaplugin.maphelper.col.declaration.IColDeclaration;
import com.franklin.ideaplugin.maphelper.col.operation.ColOperationFactory;
import com.franklin.ideaplugin.maphelper.col.method.IColQueryMethod;
import com.franklin.ideaplugin.maphelper.col.operation.IColReadWriteOperation;
import com.franklin.ideaplugin.maphelper.resolver.impl.map.MapMemberResolverFactory;
import com.franklin.ideaplugin.maphelper.utils.PsiColUtils;
import com.franklin.ideaplugin.maphelper.utils.PsiMapUtils;
import com.google.common.collect.Sets;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;

import java.util.Collection;
import java.util.Objects;
import java.util.Set;

/**
 * 从map中取出来的collection
 *
 * @author Ye Junhui
 * @since 2024/3/20
 */
public class MapCollectionMethodCallExpressionColMemberResolver implements ICollectionMemberResolver {

    public final static MapCollectionMethodCallExpressionColMemberResolver INSTANCE = new MapCollectionMethodCallExpressionColMemberResolver();

    @Override
    public boolean supports(IColDeclaration colDeclaration) {
        IDeclaration declaration = colDeclaration.getDeclaration();
        //校验类型
        PsiType psiType = declaration.getPsiType();
        if (Objects.isNull(psiType)){
            return false;
        }
        if (!PsiClassType.class.isInstance(psiType)) {
            return false;
        }
        PsiClassType psiClassType = (PsiClassType) psiType;
        PsiClass psiClass = psiClassType.resolve();
        if (!PsiClassUtils.isJavaCollectionClass(psiClass)) {
            return false;
        }
        //调用方法表达式
        PsiMethodCallExpression psiMethodCallExpression = declaration.getCreateExpression(PsiMethodCallExpression.class);

        //调用者
        PsiExpression callerExpression = psiMethodCallExpression.getMethodExpression().getQualifierExpression();
        if (Objects.isNull(callerExpression)){
            return false;
        }

        //调用者类型
        PsiType callerType = callerExpression.getType();
        if (Objects.isNull(callerType) || !PsiClassType.class.isInstance(callerType)){
            return false;
        }
        PsiClassType classType = (PsiClassType) callerType;
        PsiClass callerClass = classType.resolve();
        if (!PsiClassUtils.isJavaMapClass(callerClass)){
            return false;
        }

        //调用方法
        PsiMethod psiMethod = psiMethodCallExpression.resolveMethod();
        if (Objects.isNull(psiMethod)){
            return false;
        }

        //寻找查询方法
        IColReadWriteOperation matchOperation = ColOperationFactory.matchOperation(
                psiMethod,
                ColOperationFactory.MAP_READ_WRITE_OPERATIONS,
                colReadWriteOperation -> {
                    IColQueryMethod colQueryMethod = PsiColUtils.findColQueryMethod(psiMethod, colReadWriteOperation.getQueryMethods());
                    return Objects.nonNull(colQueryMethod);
                }
        );
        return Objects.nonNull(matchOperation);
    }

    @Override
    public Collection<IColMember> resolveColMembers(PsiElement psiExpression, IColDeclaration colDeclaration) {
        //结果
        Set<IColMember> result = Sets.newLinkedHashSet();

        //当前代码块
        Collection<IColMember> currentMembers = CollectionNewExpressionColMemberResolver.INSTANCE.resolveColMembers(psiExpression, colDeclaration);
        CollectionUtil.addAll(result,currentMembers);

        //寻找父map
        PsiElement psiElement = colDeclaration.getDeclaration().getVariable().getPsiElement();
        //类型强转表达式
        //父map get子map表达式
        PsiMethodCallExpression parentMethodCallExpression = PsiTreeUtil.findChildOfType(psiElement, PsiMethodCallExpression.class);
        PsiReferenceExpression parentReferenceExpression = PsiTreeUtil.getChildOfType(parentMethodCallExpression, PsiReferenceExpression.class);

        //父map 调用方法
        PsiIdentifier psiIdentifier = PsiTreeUtil.getChildOfType(parentReferenceExpression, PsiIdentifier.class);
        if (Objects.isNull(psiIdentifier)){
            return result;
        }

        //查询方法
        IColQueryMethod colQueryMethod = getMapQueryMethod(colDeclaration);
        if (Objects.isNull(colQueryMethod)){
            return result;
        }

        //父map变量
        PsiReferenceExpression realParentReferenceExpression = PsiTreeUtil.getChildOfType(parentReferenceExpression, PsiReferenceExpression.class);
        //父map定义
        IColDeclaration parentMapDeclaration = PsiMapUtils.findMapExpressionDeclaration(realParentReferenceExpression);
        if (Objects.isNull(parentMapDeclaration)){
            return result;
        }

        //寻找父map get子map的key
        PsiExpressionList psiExpressionList = PsiTreeUtil.findChildOfType(parentMethodCallExpression, PsiExpressionList.class);
        if (Objects.isNull(psiExpressionList)){
            return result;
        }

        //key索引
        int queryTargetIndex = colQueryMethod.getQueryTargetIndex();
        if (queryTargetIndex < 0){
            return result;
        }

        //索引越界，直接返回
        if (psiExpressionList.getExpressionCount() <= queryTargetIndex){
            return result;
        }

        //根据索引获取key
        PsiExpression keyExpression = psiExpressionList.getExpressions()[queryTargetIndex];

        //目标key
        String targetKeyText = keyExpression.getText();

        //寻找父map的成员
        MapMemberResolverFactory mapMemberResolverFactory = MapMemberResolverFactory.getInstance();
        Collection<IColMember> parentMembers = mapMemberResolverFactory.resolveExpression(parentReferenceExpression, parentMapDeclaration);
        if (CollectionUtil.isEmpty(parentMembers)){
            return result;
        }

        //匹配成员
        for (IColMember parentMember : parentMembers) {
            String keyText = parentMember.getKeyText();
            if (keyText.equals(targetKeyText)){
                //匹配成功
                Collection<IColMember> colMembers = parentMember.getChildren(getColMemberResolverFactory());
                CollectionUtil.addAll(result,colMembers);
            }
        }
        return result;
    }

    /**
     * 获取查询操作
     * @param colDeclaration
     * @return
     */
    private IColQueryMethod getMapQueryMethod(IColDeclaration colDeclaration){
        return PsiColUtils.findColQueryMethod(colDeclaration, ColOperationFactory.MAP_READ_WRITE_OPERATIONS);
    }
}
